/*
 * Copyright (c) 2015-2018 Sfkj Science And Technology Co.,Ltd.
 * All Rights Reserved.
 * This software is the confidential and proprietary information of
 * Sfkj Science And Technology Co.,Ltd.
 * ("Confidential Information").You shall not
 * disclose such Confidential Information and shall use it only in
 * accordance with the terms of the license agreement you entered into
 * with Sfkj.
 */
package com.sfkj.walk.command.user;

import com.querydsl.core.BooleanBuilder;
import com.sfkj.walk.api.query.user.SocialAccountOneByPredicateQuery;
import com.sfkj.walk.api.user.AuthenticateCommand;
import com.sfkj.walk.api.user.SocialAccountType;
import com.sfkj.walk.query.user.QSocialAccount;
import com.sfkj.walk.query.user.SocialAccount;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.axonframework.commandhandling.CommandHandler;
import org.axonframework.commandhandling.model.Repository;
import org.axonframework.queryhandling.QueryGateway;
import org.axonframework.spring.config.AxonConfiguration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.Objects;

@Slf4j
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@Service
public class UserCommandHandler {

    private final PasswordEncoder passwordEncoder;
    private final QueryGateway queryGateway;
    private final AxonConfiguration axonConfiguration;

    private Repository<User> repository;

    @CommandHandler
    public String handle(AuthenticateCommand command) {
        BooleanBuilder conditions = new BooleanBuilder();
        conditions.and(QSocialAccount.socialAccount.socialAccountType.eq(SocialAccountType.PHONE));
        conditions.and(QSocialAccount.socialAccount.openId.eq(command.getPrincipal()));

        SocialAccountOneByPredicateQuery query = new SocialAccountOneByPredicateQuery();
        query.setPredicate(conditions);

        SocialAccount socialAccount = queryGateway.send(query, SocialAccount.class).getNow(null);

        if (Objects.isNull(socialAccount)) {
            return null;
        }

        String userId = socialAccount.getUserId();

        boolean success = getRepository().load(userId).invoke((u) -> u.authenticate(command.getPassword(), passwordEncoder));

        return success ? userId : null;
    }

    public Repository<User> getRepository() {
        if (Objects.isNull(repository)) {
            repository = axonConfiguration.repository(User.class);
        }
        return repository;
    }
}